#ifndef CEPOLLCLIENTDATAMGR_H
#define CEPOLLCLIENTDATAMGR_H

//是否测试代码
#define DEF_TEST 1

#include "tcpstruct.h"

#include <QObject>
#include <QMap>
#include <QMutex>
#include <QHostAddress>
#include <QElapsedTimer>
#include <netinet/tcp.h>

class CClientData;

//客户端信息
class CClientProcess : public QObject
{
    Q_OBJECT
public:
    //解析结果返回值
    enum EProcRtn
    {
        enUnknown = 0,          //未知结果
        enSuccess,              //返回成功:报文完整，向客户端报告成功
        enFail,                 //返回失败:报文完整，向客户端报告错误
        enWait,                 //返回等待:报文不完整，等待重新解析，不向客户端报告错误
    };
public:
    explicit CClientProcess(int nClientFd, QObject* parent = nullptr);
    ~CClientProcess() { m_bRecvConnected = false; }

    //配置客户端连接信息
    void setCfg(QHostAddress addr, quint16 nPort);
    //配置
    void setClientData(CClientData* pData) { m_pClient = pData; }
    //接收信息
    void appendRecvData(QByteArray& data);

    bool isComplete() const;

private:
    /***********************报文解析与数据处理***********************/
    //解析报文
    int processData(QByteArray& byteData, CKYTXHeader* pHeader);

    //解析报文 101 测点列表
    int processDataTags(QByteArray& byteData, CKYTXHeader* pHeader);
    //处理点表接收
    int handleTagListChange(QByteArray& sData, CKYTXHeader* pHeader, CKYTXTagsInfo* pInfo);
    //写测点信息文件
    int handleWriteTagFile(const QString& sTagInfo);

    //解析报文 102 测点实时数据
    int processDataRealData(QByteArray& byteData, CKYTXHeader* pHeader);
    //解析报文 103 报警数据
    int processDataWarning(QByteArray& byteData, CKYTXHeader* pHeader);
    //解析报文 104 状态数据
    int processDataStatus(QByteArray& byteData, CKYTXHeader* pHeader);
    //解析报文 105 历史数据
    int processDataHistory(QByteArray& byteData, CKYTXHeader* pHeader);
    //解析报文 106 日志
    int processDataLog(QByteArray& byteData, CKYTXHeader* pHeader);

    /*************************************************************/
    //获取Quint16
    inline quint16 getQuint16(const QByteArray& byte, const int& nIndex = 0);
    //回复解析
    int sendRecvStatus(int nSuccess, int nFunc = 0, QString sVal = QString());
    //发送日志
    void addLogMsg(int nLevel, const QString& sMsg);

signals:
    //传日志信息
    void sigLogMsg(int nFd, int nLevel, const QString&, const QString&);
    //传解析返回值
    void sigSendRecvStatus(int nSuccess);
    //客户端重载
    void sigClientTagReload(const QString& sClient);

public:
    QMutex          m_mutex;
    QElapsedTimer*  m_pTimer;
    bool            m_bRecvConnected;

    //客户端信息
    int             m_nClientFd;        //客户端索引
    QHostAddress    m_addr;             //ip
    quint16         m_nPort;            //port
    QString         m_sGuid;            //ip:port
    CClientData*    m_pClient;          //客户端数据

    //待处理数据
    QByteArray      m_byteBuffer;       //数据缓冲
    QString         m_sTagData;         //点表数据缓冲
    int             m_nExpectSize;      //预期总数据长度
    int             m_nReceivedSize;    //已接收的数据长度

    quint8          m_nReplyByte0;
    quint8          m_nReplyByte1;

};

class CEpollClientDataMgr
{
public:
    static CClientProcess* getClientProcess(int nClientFD)
    {
        QMutexLocker locker(&m_mutex);
        if (false == m_mapClient.contains(nClientFD))
        {
            CClientProcess* pClient = new CClientProcess(nClientFD);
            m_mapClient.insert(nClientFD, pClient);
        }
        return m_mapClient.value(nClientFD);
    }
private:
    static QMap<int, CClientProcess*> m_mapClient;
    static QMutex m_mutex;
};

#endif // CEPOLLCLIENTDATAMGR_H
